package routers

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strconv"

	"shqsoft.cn/pasnj/base"
	"shqsoft.cn/pasnj/entity"
	po "shqsoft.cn/pasnj/popedom"

	"strings"

	//log "github.com/sirupsen/logrus"
	jwt "github.com/dgrijalva/jwt-go"
	"github.com/labstack/echo"
)

// Ntlm Ntlm认证信息
type Ntlm struct {
	Domain      string `json:"domain"`
	Username    string `json:"username"`
	Password    string `json:"password"`
	Workstation string `json:"workstation"`
}

// SSRSReportRouter SSRS报表请求路由
func SSRSReportRouter(c echo.Context) error {
	permID := c.Param("PermID")
	if permID == "" {
		return echo.NewHTTPError(http.StatusBadRequest, "PermID不能为空！")
	}
	pID, err := strconv.Atoi(permID)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, "PermID必须为整数！")
	}
	base.ReportDef.GetReportItem(pID)
	rItem := base.ReportDef.GetReportItem(pID)
	if rItem == nil {
		return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("没有找到PermID:%s对应的报表定义！", permID))
	}
	var params map[string]string
	jsonStr := c.FormValue("ReportParams")
	if jsonStr != "" {
		err := json.Unmarshal([]byte(jsonStr), &params)
		if err != nil {
			return echo.NewHTTPError(http.StatusBadRequest, err.Error())
		}
	}
	report := base.NewSSRSReport()
	url, err := report.GetURL(rItem.FileName, params)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	resp, err := report.ConnReport(url)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	defer resp.Body.Close()
	by, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	return c.HTML(http.StatusOK, string(by))
}

// ReportParamSearchRouter 报表参数自动搜索路由
func ReportParamSearchRouter(c echo.Context) error {
	var params map[string]string
	jsonStr := c.FormValue("SearchParams")
	if jsonStr == "" {
		return echo.NewHTTPError(http.StatusBadRequest, "SearchParams不能为空！")
	}
	err := json.Unmarshal([]byte(jsonStr), &params)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	repIDStr, ok := params["reportID"]
	if !ok || repIDStr == "" {
		return echo.NewHTTPError(http.StatusBadRequest, "SearchParams中没有参数reportID！")
	}
	paramName, ok := params["paramName"]
	if !ok || paramName == "" {
		return echo.NewHTTPError(http.StatusBadRequest, "SearchParams中没有参数paramName！")
	}
	searchValue, ok := params["searchValue"]
	if !ok || searchValue == "" {
		return echo.NewHTTPError(http.StatusBadRequest, "SearchParams中没有参数searchValue！")
	}
	repID, err := strconv.Atoi(repIDStr)
	if !ok || searchValue == "" {
		return echo.NewHTTPError(http.StatusBadRequest, "参数reportID必须是Int类型！")
	}
	rItem := base.ReportDef.GetReportItem(repID)
	opts, err := rItem.SearchOption(paramName, searchValue)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err)
	}
	return c.JSON(http.StatusOK, opts)
}

// NtlmOptionsRouter Ntlm配置信息
func NtlmOptionsRouter(c echo.Context) error {
	ntlm := &Ntlm{
		Domain:      base.Context.SSRS.Domain,
		Username:    base.Context.SSRS.UserName,
		Password:    base.Context.SSRS.Password,
		Workstation: base.Context.SSRS.Workstation,
	}
	return c.JSON(http.StatusOK, ntlm)
}

// url 配置信息URL
func GetReportRouterUrl(c echo.Context) error {
	url := base.Context.SSRS.Url
	return c.JSON(http.StatusOK, url)
}

// ReportControl 操作报表参数的控件
type ReportControl struct {
	Name         string            `json:"name"`
	Label        string            `json:"label"`
	Required     bool              `json:"required"`
	Data         []ListItem        `json:"data"`
	Grid         int               `json:"grid"`
	Multiple     bool              `json:"multiple"`
	ControlType  string            `json:"type"`
	DefaultValue string            `json:"defaultValue"`
	IsDisabled   bool              `json:"isDisabled"`
	DataType     string            `json:"dataType"`
	Layout       Layout            `json:"layout"`
	DefaultLabel string            `json:"defaultLabel"`
	Props        map[string]string `json:"props"`
}

// Layout 参数项布局
type Layout struct {
	LabelSpan   int `json:"labelSpan"`
	WrapperSpan int `json:"wrapperSpan"`
}

// ListItem 列表数据
type ListItem struct {
	Value string `json:"value"`
	Label string `json:"label"`
}

// ReportControlsRouter 获取操作报表参数的控件的路由
func ReportControlsRouter(c echo.Context) error {
	//获取数据源
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(*UserLoginClaims)
	permID := c.Param("PermID")
	uID := strconv.Itoa(claims.OrganID)
	UserID := strconv.Itoa(claims.UserID)
	ParentOrgID := strconv.Itoa(claims.ParentOrgID)
	if permID == "" {
		return echo.NewHTTPError(http.StatusBadRequest, "PermID不能为空！")
	}
	pID, err := strconv.Atoi(permID)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, "PermID必须为整数！")
	}
	rItem := base.ReportDef.GetReportItem(pID)
	if rItem == nil {
		return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("没有找到PermID:%s对应的报表定义！", permID))
	}
	pLen := len(rItem.Parameters)
	conts := make([]ReportControl, pLen)
	for i, param := range rItem.Parameters {
		conts[i].Name = param.Name
		conts[i].Label = param.Caption
		width := param.Width
		if width > 24 {
			width = round(float32(24) / float32(pLen+1))
		}
		if pLen > 5 {
			width = round(float32(24) / float32(5))
		}
		conts[i].Grid = width
		conts[i].Required = true
		conts[i].Multiple = param.IsCanMultiSelect
		conts[i].DefaultValue = param.InitValue
		editType := param.EditType
		dataType := param.EditType
		switch editType {
		case "string":
			editType = "text"
			dataType = ""
		case "auto":
			editType = "search2"
			dataType = ""

			props := make(map[string]string)
			props["reportID"] = permID
			props["paramName"] = param.Name
			conts[i].Props = props
			conts[i].DefaultLabel = param.InitLabel
		case "float":
			editType = "number"
			dataType = "number"
		}
		if editType == "hide" {
			conts[i].ControlType = "text"
			conts[i].IsDisabled = true
			dataType = ""
		} else {
			conts[i].ControlType = editType
			conts[i].DataType = dataType
		}
		conts[i].Layout = Layout{
			LabelSpan:   param.LabelSpan,
			WrapperSpan: param.WrapperSpan,
		}
		data, err := getSelectItems(rItem.FileName, UserID, uID, ParentOrgID, permID, &param)
		if err != nil {
			return echo.NewHTTPError(http.StatusBadRequest, err.Error())
		}
		conts[i].Data = data
		dVal, err := getDefaultValue(param.InitValue, claims.Sjy)
		if err != nil {
			return echo.NewHTTPError(http.StatusBadRequest, err.Error())
		}
		conts[i].DefaultValue = dVal
	}
	return c.JSON(http.StatusOK, conts)
}
func getSelectItems(rName string, UserID string, uID string, ParentOrgID string, permID string, param *base.ReportParameter) ([]ListItem, error) {
	if param.DataSourceType == "FIXED" {
		//1|本外币,2|人民币,3|外币
		items := strings.Split(param.DataExp, ",")
		listItems := make([]ListItem, len(items))
		for i, item := range items {
			val := strings.Split(item, "|")
			if len(val) != 2 {
				return nil, fmt.Errorf("解析报表%s的参数%s出错,！", rName, param.Caption)
			}
			listItems[i].Value = val[0]
			listItems[i].Label = val[1]
		}
		return listItems, nil
	} else if param.DataSourceType == "FIXEDSQL" {
		db := base.DB
		usID, err := strconv.Atoi(UserID)
		if err != nil {
			return nil, nil
		}
		pID, err := strconv.Atoi(permID)
		if err != nil {
			return nil, nil
		}
		flag := "1"
		permTypes, err := po.GetUserPermissionTypes(usID, 3013)
		for _, val := range permTypes {
			if flag == "4" {
				break
			}
			if val == "3" {
				flag = "3"
			} else if val == "J" {
				flag = "J"
			} else if val == "4" {
				flag = "4"
			}
		}
		if pID == 3013 && flag == "1" {
			param.DataExp = param.DataExp + " WHERE ID in('[员工].[所属部门].[All]')  ORDER BY OrderKey "
		}
		if pID == 3013 && flag == "3" {
			param.DataExp = param.DataExp + " WHERE ID in('[员工].[所属部门].[All]','[员工].[所属部门].&[" + uID + "]')  ORDER BY OrderKey "
		}
		if pID == 3013 && flag == "J" {
			param.DataExp = "SELECT ID,OrganName from (" +
				"SELECT '[员工].[所属部门].[All]' ID,'00000' OrganID,'全部' OrganName,0 OrderKey " +
				"UNION ALL " +
				"SELECT '[员工].[所属部门].&['+CAST(OrganID AS varchar(10))+']' ID,OrganID,OrganName,OrderKey FROM V_ParentOrgan " +
				"WHERE OrganID>0 AND ParentOrganID=" + ParentOrgID + ") t "
		}
		if pID == 3013 && flag == "4" {
			param.DataExp = "SELECT ID,OrganName from (" +
				"SELECT '[员工].[所属部门].[All]' ID,'00000' OrganID,'全部' OrganName,0 OrderKey " +
				"UNION ALL " +
				"SELECT '[员工].[所属部门].&['+CAST(OrganID AS varchar(10))+']' ID,OrganID,OrganName,OrderKey FROM V_ParentOrgan " +
				"WHERE OrganID>0 AND ParentOrganID > 0 ) t "
		}
		rows, _ := db.Raw(param.DataExp).Rows()
		var ID string
		var Name string
		var i int = 0
		listItems := make([]ListItem, 820)
		for rows.Next() {
			rows.Scan(&ID, &Name)
			listItems[i].Value = ID
			listItems[i].Label = Name
			i++
		}
		return listItems, nil
	} else if param.DataSourceType == "SQL" {
		db := base.DB
		if param.EditType == "auto" {
			sql := strings.Replace(param.DataExp, "?", param.InitLabel, -1)
			db = db.Raw(sql).Order(param.OrderBY).Limit(7)
		} else {
			db = db.Raw(param.DataExp)
		}
		rows, err := db.Rows()
		if err != nil {
			return nil, fmt.Errorf("解析报表%s的参数%s出错！%s", rName, param.Caption, err.Error())
		}
		defer rows.Close()
		var (
			value string
			label string
		)
		listItems := make([]ListItem, 0, 20)
		for rows.Next() {
			rows.Scan(&value, &label)
			li := ListItem{
				Value: value,
				Label: label,
			}
			listItems = append(listItems, li)
		}
		return listItems, nil
	}
	return nil, nil
}
func getDefaultValue(initValue string, Sjy string) (string, error) {
	var pasInfo entity.PASInfo
	err := base.DB.First(&pasInfo).Error
	if err != nil {
		return "", err
	}
	if strings.HasPrefix(initValue, "#") {
		var retVal string
		if Sjy == "EDW" {
			switch initValue {
			case "#SYSDATE":
				retVal = pasInfo.EdwCurrDate.Format("20060102")
			case "#MONTHFIRSTDAY":
				retVal = pasInfo.EdwCurrDate.Format("200601") + "01"
			case "#YEARFIRSTDAY":
				retVal = pasInfo.EdwCurrDate.Format("2006") + "0101"
			case "#SYSYEAR":
				retVal = pasInfo.EdwCurrDate.Format("2006")
			case "#SYSMONTH":
				retVal = pasInfo.EdwCurrDate.Format("200601")
			case "#SYSNEXTMONTH":
				retVal = pasInfo.EdwCurrDate.AddDate(0, 1, 0).Format("20060102")
			case "#FTPSYSDATE":
				retVal = pasInfo.FtpCurrDate.Format("20060102")
			case "#FTPSYSMONTH":
				retVal = pasInfo.FtpCurrDate.Format("200601")
			}
		} else if Sjy == "ODS" {
			switch initValue {
			case "#SYSDATE":
				retVal = pasInfo.CurrDate.Format("20060102")
			case "#MONTHFIRSTDAY":
				retVal = pasInfo.CurrDate.Format("200601") + "01"
			case "#YEARFIRSTDAY":
				retVal = pasInfo.CurrDate.Format("2006") + "0101"
			case "#SYSYEAR":
				retVal = pasInfo.CurrDate.Format("2006")
			case "#SYSMONTH":
				retVal = pasInfo.CurrDate.Format("200601")
			case "#SYSNEXTMONTH":
				retVal = pasInfo.CurrDate.AddDate(0, 1, 0).Format("20060102")
			case "#FTPSYSDATE":
				retVal = pasInfo.FtpCurrDate.Format("20060102")
			case "#FTPSYSMONTH":
				retVal = pasInfo.FtpCurrDate.Format("200601")
			case "#EDWSYSDATE":
				retVal = pasInfo.EdwCurrDate.Format("20060102")
			case "#EDWSYSMONTH":
				retVal = pasInfo.EdwCurrDate.Format("200601")
			case "#EDWMONTHFIRSTDAY":
				retVal = pasInfo.EdwCurrDate.Format("200601") + "01"
			}
		}
		return retVal, nil
	}
	return initValue, nil
}
func round(val float32) int {
	if val < 0 {
		return int(val - 0.5)
	}
	return int(val + 0.5)
}
